package gbase

import (
	"bytes"
	"fmt"
	"net/url"
	"strconv"

	"github.com/bytedance/sonic"
	"github.com/emirpasic/gods/maps/treemap"
	"github.com/henrylee2cn/ameda"
	jsoniter "github.com/json-iterator/go"
)

type Map map[string]any

// func (m Map) FromString(str string) Map {
// 	_ = jsoniter.UnmarshalFromString(str, &m)
// 	return m
// }

func (m Map) FromString(data string) error {
	if data != "" {
		return sonic.UnmarshalString(data, &m)
	}
	return nil
}

func (m Map) FromBytes(data []byte) error {
	if len(data) > 0 {
		if err := sonic.Unmarshal(data, &m); err != nil {
			return err
		}
	}
	return nil
}

// map or struct
func (m *Map) FromStruct(child any, data any) error {
	if jsonBytes, err := sonic.Marshal(data); err != nil {
		return err
	} else if err = sonic.Unmarshal(jsonBytes, child); err != nil {
		return err
	}
	return nil
}

// from URL参数格式 (key1=value1&key2=value2)
func (m Map) FromUrlParams(urlParams string) error {
	params, err := url.ParseQuery(urlParams)
	if err != nil || len(params) == 0 {
		return err
	}
	for key, values := range params {
		if len(values) == 1 {
			m[key] = values[0]
		} else {
			m[key] = values
		}
	}
	return nil
}

// from struct/map/json(string)/json([]byte)
func (m Map) FromX(v any) error {
	var (
		jsonBytes []byte
		err       error
	)
	switch val := v.(type) {
	case string:
		jsonBytes = String(val).ToBytes()
	case []byte:
		jsonBytes = val
	default:
		if jsonBytes, err = jsoniter.Marshal(v); err != nil {
			return err
		}
	}
	if err = jsoniter.Unmarshal(jsonBytes, &m); err != nil {
		return err
	}
	return nil
}

// to struct/map/string/[]byte，ptr must be pointer
func (m Map) ToX(ptr any) error {
	switch v := ptr.(type) {
	case *string:
		// 转换为JSON字符串
		*v = m.ToString()
		return nil
	case *[]byte:
		// 转换为JSON字节数组
		*v = m.ToBytes()
		return nil
	case *Map:
		// 转换为Map
		*v = m
		return nil
	default:
		// 转换为结构体或其他类型
		jsonBytes := m.ToBytes()
		return jsoniter.Unmarshal(jsonBytes, ptr)
	}
}

func (m Map) ToString() string {
	str, _ := jsoniter.MarshalToString(m)
	return str
}

// {b:xx,a:xx,c:xx} => {a:xx,b:xx,c:xx}
func (m Map) ToSortString() string {
	tm := treemap.NewWithStringComparator()
	for k, v := range m {
		tm.Put(k, v)
	}
	if jb, err := tm.ToJSON(); err != nil {
		return ""
	} else {
		return string(jb)
	}
}

// 不区分大小写的排序字符串
func (m Map) ToSortStringWithoutCase() string {
	tm := treemap.NewWith(StringComparatorWithoutCase)
	for k, v := range m {
		tm.Put(k, v)
	}
	if jb, err := tm.ToJSON(); err != nil {
		return ""
	} else {
		return string(jb)
	}
}

func (m Map) ToUrlParamsStr() string {
	var (
		str string
	)
	tm := treemap.NewWithStringComparator()
	for k, v := range m {
		tm.Put(k, v)
	}
	it := tm.Iterator()
	for it.Next() {
		str += fmt.Sprintf("%s=%s&", it.Key(), m.GetString(it.Key().(string)))
	}
	return String(str).StrRmEnd().ToString()
}

// 不区分大小写的URL参数字符串
func (m Map) ToUrlParamsStrWithoutCase() string {
	var (
		str string
	)
	tm := treemap.NewWith(StringComparatorWithoutCase)
	for k, v := range m {
		tm.Put(k, v)
	}
	it := tm.Iterator()
	for it.Next() {
		str += fmt.Sprintf("%s=%s&", it.Key(), m.GetString(it.Key().(string)))
	}
	return String(str).StrRmEnd().ToString()
}

func (m Map) ToBytes() []byte {
	//jsoniter.
	bytes, _ := jsoniter.Marshal(m)
	return bytes
}

func (m Map) ToTreeMap() (tm *treemap.Map) {
	tm = treemap.NewWithStringComparator()
	for k, v := range m {
		tm.Put(k, v)
	}
	return
}

// 不区分大小写的TreeMap
// func (m Map) ToTreeMapCaseInsensitive() (tm *treemap.Map) {
// 	tm = treemap.NewWith(StringComparatorWithOutCase)
// 	for k, v := range m {
// 		tm.Put(k, v)
// 	}
// 	return
// }

func (m Map) IsEmpty() bool {
	return len(m) == 0
}

func (m Map) GetInt(key string) int {
	v, _ := ameda.StringToInt(fmt.Sprintf("%v", m[key]))
	return v
}

func (m Map) GetInt64(key string) int64 {
	//logs.Debug("m.key",key,m[key])
	var (
		value string
	)
	switch m[key].(type) {
	case float64, float32:
		value = fmt.Sprintf("%.f", m[key])
	case string:
		value = m[key].(string)
	case bool:
		value = fmt.Sprintf("%v", m[key])
	default:
		value = fmt.Sprintf("%d", m[key])
	}
	v, _ := ameda.StringToInt64(value)
	return v
}

func (m Map) GetString(key string) string {
	switch v := m[key].(type) {
	case float64:
		return strconv.FormatFloat(v, 'f', -1, 64)
	case float32:
		return strconv.FormatFloat(float64(v), 'f', -1, 64)
	case string:
		return v
	case int8:
		return strconv.FormatInt(int64(v), 10)
	case int16:
		return strconv.FormatInt(int64(v), 10)
	case int:
		return strconv.FormatInt(int64(v), 10)
	case int32:
		return strconv.FormatInt(int64(v), 10)
	case int64:
		return strconv.FormatInt(v, 10)
	case bool:
		return strconv.FormatBool(v)
	default:
		return fmt.Sprintf("%v", m[key])
	}
}

func (m Map) GetBool(key string) bool {
	switch m[key].(type) {
	case bool:
		return m[key].(bool)
	default:
		return false
	}
}

func (m Map) Exist(keys ...string) bool {
	for _, v := range keys {
		if _, exist := m[v]; !exist {
			return false
		}
	}
	return true
}

func (m Map) RemoveKeys(keys ...string) Map {
	for _, v := range keys {
		delete(m, v)
	}
	return m
}

// cm参数覆盖m
func (m Map) Combine(cm Map) Map {
	for k, v := range cm {
		m[k] = v
	}
	return m
}

func (m Map) ToXmlStr() string {
	var buffer bytes.Buffer
	buffer.WriteString(`<?xml version="1.0" encoding="UTF-8"?>`) // 写入 XML 头部

	err := mapToXmlElement(&buffer, m, "root") // 默认使用 "root" 作为根标签
	if err != nil {
		return ""
	}

	return buffer.String()
}
